﻿using System;

internal class PaletteTable
{
    private int currentContrast;
    private int currentEmph = -1;
    private int currentHue;
    private int currentLightness;
    private int currentSaturation;
    internal static int[] curTable = new int[0x40];
    internal static int[,] emphTable = new int[8, 0x40];
    internal static int[] origTable = new int[0x40];

    internal int getBlue(int rgb)
    {
        return (rgb & 0xff);
    }

    internal int getEntry(int yiq)
    {
        return curTable[yiq];
    }

    internal int getGreen(int rgb)
    {
        return ((rgb >> 8) & 0xff);
    }

    internal int getHue(int hsl)
    {
        return ((hsl >> 0x10) & 0xff);
    }

    internal int getLightness(int hsl)
    {
        return (hsl & 0xff);
    }

    internal int getRed(int rgb)
    {
        return ((rgb >> 0x10) & 0xff);
    }

    internal int getRgb(int r, int g, int b)
    {
        return (((r << 0x10) | (g << 8)) | b);
    }

    internal int getSaturation(int hsl)
    {
        return ((hsl >> 8) & 0xff);
    }

    internal int HSBtoRGB(int h, int s, int l)
    {
        return this.HSBtoRGB((float) h, (float) s, (float) l);
    }

    internal int HSBtoRGB(float h, float s, float l)
    {
        float num = h / 60f;
        float num2 = (s * 255f) / 100f;
        float num3 = (l * 255f) / 100f;
        float num4 = Math.Max(num, Math.Max(num2, num3));
        if (num2 == 0f)
        {
            return 0;
        }
        float num5 = (num2 * num4) / 255f;
        int r = 0;
        int g = 0;
        int b = 0;
        if (num > 3f)
        {
            b = (int) num4;
            if (num > 4f)
            {
                g = (int) (num4 - num5);
                r = ((int) ((h - 4f) * num5)) + g;
            }
            else
            {
                r = (int) (num4 - num5);
                g = r - ((int) ((h - 4f) * num5));
            }
        }
        else if (num > 1f)
        {
            g = (int) num4;
            if (num > 2f)
            {
                r = (int) (num4 - num5);
                b = ((int) ((h - 2f) * num5)) + r;
            }
            else
            {
                b = (int) (num4 - num5);
                r = b - ((int) ((h - 2f) * num5));
            }
        }
        else
        {
            r = (int) num4;
            if (h > 0f)
            {
                b = (int) (num4 - num5);
                g = ((int) (h * num5)) + b;
            }
            else
            {
                g = (int) (num4 - num5);
                b = g - ((int) (h * num5));
            }
        }
        return this.getRgb(r, g, b);
    }

    internal int HSLtoRGB(int hsl)
    {
        float h = (float) (((double) ((hsl >> 0x10) & 0xff)) / 255.0);
        float s = (float) (((double) ((hsl >> 8) & 0xff)) / 255.0);
        float l = (float) (((double) (hsl & 0xff)) / 255.0);
        return this.HSBtoRGB(h, s, l);
    }

    internal int HSLtoRGB(int h, int s, int l)
    {
        return this.HSBtoRGB((float) (((float) h) / 255f), (float) (((float) s) / 255f), (float) (((float) l) / 255f));
    }

    internal void loadDefaultPalette()
    {
        if (origTable == null)
        {
            origTable = new int[0x40];
        }
        origTable[0] = this.getRgb(0x7c, 0x7c, 0x7c);
        origTable[1] = this.getRgb(0, 0, 0xfc);
        origTable[2] = this.getRgb(0, 0, 0xbc);
        origTable[3] = this.getRgb(0x44, 40, 0xbc);
        origTable[4] = this.getRgb(0x94, 0, 0x84);
        origTable[5] = this.getRgb(0xa8, 0, 0x20);
        origTable[6] = this.getRgb(0xa8, 0x10, 0);
        origTable[7] = this.getRgb(0x88, 20, 0);
        origTable[8] = this.getRgb(80, 0x30, 0);
        origTable[9] = this.getRgb(0, 120, 0);
        origTable[10] = this.getRgb(0, 0x68, 0);
        origTable[11] = this.getRgb(0, 0x58, 0);
        origTable[12] = this.getRgb(0, 0x40, 0x58);
        origTable[13] = this.getRgb(0, 0, 0);
        origTable[14] = this.getRgb(0, 0, 0);
        origTable[15] = this.getRgb(0, 0, 0);
        origTable[0x10] = this.getRgb(0xbc, 0xbc, 0xbc);
        origTable[0x11] = this.getRgb(0, 120, 0xf8);
        origTable[0x12] = this.getRgb(0, 0x58, 0xf8);
        origTable[0x13] = this.getRgb(0x68, 0x44, 0xfc);
        origTable[20] = this.getRgb(0xd8, 0, 0xcc);
        origTable[0x15] = this.getRgb(0xe4, 0, 0x58);
        origTable[0x16] = this.getRgb(0xf8, 0x38, 0);
        origTable[0x17] = this.getRgb(0xe4, 0x5c, 0x10);
        origTable[0x18] = this.getRgb(0xac, 0x7c, 0);
        origTable[0x19] = this.getRgb(0, 0xb8, 0);
        origTable[0x1a] = this.getRgb(0, 0xa8, 0);
        origTable[0x1b] = this.getRgb(0, 0xa8, 0x44);
        origTable[0x1c] = this.getRgb(0, 0x88, 0x88);
        origTable[0x1d] = this.getRgb(0, 0, 0);
        origTable[30] = this.getRgb(0, 0, 0);
        origTable[0x1f] = this.getRgb(0, 0, 0);
        origTable[0x20] = this.getRgb(0xf8, 0xf8, 0xf8);
        origTable[0x21] = this.getRgb(60, 0xbc, 0xfc);
        origTable[0x22] = this.getRgb(0x68, 0x88, 0xfc);
        origTable[0x23] = this.getRgb(0x98, 120, 0xf8);
        origTable[0x24] = this.getRgb(0xf8, 120, 0xf8);
        origTable[0x25] = this.getRgb(0xf8, 0x58, 0x98);
        origTable[0x26] = this.getRgb(0xf8, 120, 0x58);
        origTable[0x27] = this.getRgb(0xfc, 160, 0x44);
        origTable[40] = this.getRgb(0xf8, 0xb8, 0);
        origTable[0x29] = this.getRgb(0xb8, 0xf8, 0x18);
        origTable[0x2a] = this.getRgb(0x58, 0xd8, 0x54);
        origTable[0x2b] = this.getRgb(0x58, 0xf8, 0x98);
        origTable[0x2c] = this.getRgb(0, 0xe8, 0xd8);
        origTable[0x2d] = this.getRgb(120, 120, 120);
        origTable[0x2e] = this.getRgb(0, 0, 0);
        origTable[0x2f] = this.getRgb(0, 0, 0);
        origTable[0x30] = this.getRgb(0xfc, 0xfc, 0xfc);
        origTable[0x31] = this.getRgb(0xa4, 0xe4, 0xfc);
        origTable[50] = this.getRgb(0xb8, 0xb8, 0xf8);
        origTable[0x33] = this.getRgb(0xd8, 0xb8, 0xf8);
        origTable[0x34] = this.getRgb(0xf8, 0xb8, 0xf8);
        origTable[0x35] = this.getRgb(0xf8, 0xa4, 0xc0);
        origTable[0x36] = this.getRgb(240, 0xd0, 0xb0);
        origTable[0x37] = this.getRgb(0xfc, 0xe0, 0xa8);
        origTable[0x38] = this.getRgb(0xf8, 0xd8, 120);
        origTable[0x39] = this.getRgb(0xd8, 0xf8, 120);
        origTable[0x3a] = this.getRgb(0xb8, 0xf8, 0xb8);
        origTable[0x3b] = this.getRgb(0xb8, 0xf8, 0xd8);
        origTable[60] = this.getRgb(0, 0xfc, 0xfc);
        origTable[0x3d] = this.getRgb(0xd8, 0xd8, 0x10);
        origTable[0x3e] = this.getRgb(0, 0, 0);
        origTable[0x3f] = this.getRgb(0, 0, 0);
        this.setEmphasis(0);
        this.makeTables();
    }

    internal void makeTables()
    {
        for (int i = 0; i < 8; i++)
        {
            float num6 = 1f;
            float num7 = 1f;
            float num8 = 1f;
            if ((i & 1) != 0)
            {
                num6 = 0.75f;
                num8 = 0.75f;
            }
            if ((i & 2) != 0)
            {
                num6 = 0.75f;
                num7 = 0.75f;
            }
            if ((i & 4) != 0)
            {
                num7 = 0.75f;
                num8 = 0.75f;
            }
            for (int j = 0; j < 0x40; j++)
            {
                int rgb = origTable[j];
                int r = (int) (this.getRed(rgb) * num6);
                int g = (int) (this.getGreen(rgb) * num7);
                int b = (int) (this.getBlue(rgb) * num8);
                emphTable[i, j] = this.getRgb(r, g, b);
            }
        }
    }

    internal void reset()
    {
        this.currentEmph = 0;
        this.currentHue = 0;
        this.currentSaturation = 0;
        this.currentLightness = 0;
        this.setEmphasis(0);
        this.updatePalette();
    }

    internal float[] RGBtoHSB(int b, int g, int r, float[] vals)
    {
        float num = Math.Max(r, Math.Max(b, g));
        float num2 = num - Math.Min(r, Math.Min(g, b));
        float num3 = (num * 100f) / 255f;
        float num4 = (255f * num2) / num;
        float num5 = -1f;
        if (num == r)
        {
            num5 = ((float) (g - b)) / num2;
        }
        else if (num == g)
        {
            num5 = ((float) (b - r)) / num2;
        }
        else if (num == b)
        {
            num5 = 4f + (((float) (r - g)) / num2);
        }
        num5 *= 60f;
        if (num5 < 0f)
        {
            num5 += 360f;
        }
        vals[0] = num5;
        vals[1] = num4;
        vals[2] = num3;
        return vals;
    }

    internal int RGBtoHSL(int rgb)
    {
        return this.RGBtoHSL((rgb >> 0x10) & 0xff, (rgb >> 8) & 0xff, rgb & 0xff);
    }

    internal int RGBtoHSL(int r, int g, int b)
    {
        float[] vals = new float[3];
        vals = this.RGBtoHSB(b, g, r, vals);
        vals[0] -= (float) Math.Floor((double) vals[0]);
        int num = 0;
        num |= ((int) (vals[0] * 255.0)) << 0x10;
        num |= ((int) (vals[1] * 255.0)) << 8;
        return (num | ((int) (vals[2] * 255.0)));
    }

    internal void setEmphasis(int emph)
    {
        if (emph != this.currentEmph)
        {
            this.currentEmph = emph;
            for (int i = 0; i < 0x40; i++)
            {
                curTable[i] = emphTable[emph, i];
            }
            this.updatePalette();
        }
    }

    internal void updatePalette()
    {
        this.updatePalette(this.currentHue, this.currentSaturation, this.currentLightness, this.currentContrast);
    }

    internal void updatePalette(int hueAdd, int saturationAdd, int lightnessAdd, int contrastAdd)
    {
        if (contrastAdd > 0)
        {
            contrastAdd *= 4;
        }
        for (int i = 0; i < 0x40; i++)
        {
            int hsl = this.RGBtoHSL(emphTable[this.currentEmph, i]);
            int h = this.getHue(hsl) + hueAdd;
            int s = (int) (this.getSaturation(hsl) * (1.0 + (((float) saturationAdd) / 256f)));
            int l = this.getLightness(hsl);
            if (h < 0)
            {
                h += 0xff;
            }
            if (s < 0)
            {
                s = 0;
            }
            if (l < 0)
            {
                l = 0;
            }
            if (h > 0xff)
            {
                h -= 0xff;
            }
            if (s > 0xff)
            {
                s = 0xff;
            }
            if (l > 0xff)
            {
                l = 0xff;
            }
            int rgb = this.HSLtoRGB(h, s, l);
            int r = this.getRed(rgb);
            int g = this.getGreen(rgb);
            int b = this.getBlue(rgb);
            r = (0x80 + lightnessAdd) + ((int) ((r - 0x80) * (1.0 + (((float) contrastAdd) / 256f))));
            g = (0x80 + lightnessAdd) + ((int) ((g - 0x80) * (1.0 + (((float) contrastAdd) / 256f))));
            b = (0x80 + lightnessAdd) + ((int) ((b - 0x80) * (1.0 + (((float) contrastAdd) / 256f))));
            if (r < 0)
            {
                r = 0;
            }
            if (g < 0)
            {
                g = 0;
            }
            if (b < 0)
            {
                b = 0;
            }
            if (r > 0xff)
            {
                r = 0xff;
            }
            if (g > 0xff)
            {
                g = 0xff;
            }
            if (b > 0xff)
            {
                b = 0xff;
            }
            rgb = this.getRgb(r, g, b);
            curTable[i] = origTable[i];
        }
        this.currentHue = hueAdd;
        this.currentSaturation = saturationAdd;
        this.currentLightness = lightnessAdd;
        this.currentContrast = contrastAdd;
    }

    internal bool loadNTSCPalette()
    {
        return false;
    }
}

